From 3953bb4d72ebd257e04beffd11a369823b6bd306 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Mon, 5 Jan 2004 15:20:55 +0000 Subject: [PATCH] bitkeeper revision 1.666 (3ff980d7gcf3e_3nqJ9SkvI1vvfOIw) dev.c, skbuff.h, netdevice.h: Fix network packet receive ordering. --- xen/include/xeno/netdevice.h | 7 +++---- xen/include/xeno/skbuff.h | 10 ---------- xen/net/dev.c | 35 ++++++++++++++++++++--------------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/xen/include/xeno/netdevice.h b/xen/include/xeno/netdevice.h index ea7f56e38e..7b1d3d7ea0 100644 --- a/xen/include/xeno/netdevice.h +++ b/xen/include/xeno/netdevice.h @@ -30,7 +30,7 @@ #include #include #include - +#include #include #include #include @@ -41,9 +41,8 @@ struct vlan_group; extern struct skb_completion_queues { - struct sk_buff *rx; /* Packets received in interrupt context. */ - unsigned int rx_qlen; - struct sk_buff *tx; /* Tx buffers defunct in interrupt context. */ + struct sk_buff_head rx; /* Packets received in interrupt context. */ + struct sk_buff *tx; /* Tx buffers defunct in interrupt context. */ } skb_queue[NR_CPUS] __cacheline_aligned; /* Backlog congestion levels */ diff --git a/xen/include/xeno/skbuff.h b/xen/include/xeno/skbuff.h index ea83a5210f..4325deb4ae 100644 --- a/xen/include/xeno/skbuff.h +++ b/xen/include/xeno/skbuff.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -88,9 +87,7 @@ struct sk_buff_head { /* These two members must be first. */ struct sk_buff * next; struct sk_buff * prev; - __u32 qlen; - spinlock_t lock; }; #define MAX_SKB_FRAGS 1 /* KAF: was 6 */ @@ -204,7 +201,6 @@ static inline __u32 skb_queue_len(struct sk_buff_head *list_) static inline void skb_queue_head_init(struct sk_buff_head *list) { - spin_lock_init(&list->lock); list->prev = (struct sk_buff *)list; list->next = (struct sk_buff *)list; list->qlen = 0; @@ -215,9 +211,6 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) * @list: list to use * @newsk: buffer to queue * - * Queue a buffer at the start of a list. This function takes no locks - * and you must therefore hold required locks before calling it. - * * A buffer cannot be placed on two lists at the same time. */ @@ -240,9 +233,6 @@ static inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *n * @list: list to use * @newsk: buffer to queue * - * Queue a buffer at the end of a list. This function takes no locks - * and you must therefore hold required locks before calling it. - * * A buffer cannot be placed on two lists at the same time. */ diff --git a/xen/net/dev.c b/xen/net/dev.c index ac60f125bb..a20a0ee6cd 100644 --- a/xen/net/dev.c +++ b/xen/net/dev.c @@ -582,18 +582,13 @@ int netif_rx(struct sk_buff *skb) unsigned long flags; local_irq_save(flags); - - if ( unlikely(skb_queue[cpu].rx_qlen > 100) ) + if ( unlikely(skb_queue_len(&skb_queue[cpu].rx) > 100) ) { local_irq_restore(flags); perfc_incr(net_rx_congestion_drop); return NET_RX_DROP; } - - skb->next = skb_queue[cpu].rx; - skb_queue[cpu].rx = skb; - skb_queue[cpu].rx_qlen++; - + __skb_queue_tail(&skb_queue[cpu].rx, skb); local_irq_restore(flags); __cpu_raise_softirq(cpu, NET_RX_SOFTIRQ); @@ -604,15 +599,25 @@ int netif_rx(struct sk_buff *skb) static void net_rx_action(struct softirq_action *h) { int offset, cpu = smp_processor_id(); - struct sk_buff *skb, *nskb; + struct sk_buff_head list, *q = &skb_queue[cpu].rx; + struct sk_buff *skb; local_irq_disable(); - skb = skb_queue[cpu].rx; - skb_queue[cpu].rx = NULL; - skb_queue[cpu].rx_qlen = 0; + /* Code to patch to the private list header is invalid if list is empty! */ + if ( unlikely(skb_queue_len(q) == 0) ) + { + local_irq_enable(); + return; + } + /* Patch the head and tail skbuffs to point at the private list header. */ + q->next->prev = (struct sk_buff *)&list; + q->prev->next = (struct sk_buff *)&list; + /* Move the list to our private header. The public header is reinit'ed. */ + list = *q; + skb_queue_head_init(q); local_irq_enable(); - while ( skb != NULL ) + while ( (skb = __skb_dequeue(&list)) != NULL ) { ASSERT(skb->skb_type == SKB_ZERO_COPY); @@ -646,9 +651,7 @@ static void net_rx_action(struct softirq_action *h) unmap_domain_mem(skb->head); - nskb = skb->next; kfree_skb(skb); - skb = nskb; } } @@ -2336,10 +2339,12 @@ static void make_rx_response(net_vif_t *vif, int setup_network_devices(void) { - int ret; + int i, ret; extern char opt_ifname[]; memset(skb_queue, 0, sizeof(skb_queue)); + for ( i = 0; i < smp_num_cpus; i++ ) + skb_queue_head_init(&skb_queue[i].rx); /* Actual receive processing happens in softirq context. */ open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); -- 2.30.2